#include "sv2_video_base.h"
#include <opencv2/aruco.hpp>


namespace sv2 {
  
VideoStreamerBase::VideoStreamerBase()
{
  this->_is_running = false;
}
VideoStreamerBase::~VideoStreamerBase()
{
  this->release();
}
cv::Size VideoStreamerBase::getSize()
{
  return this->_stream_size;
}
int VideoStreamerBase::getPort()
{
  return this->_port;
}
std::string VideoStreamerBase::getUrl()
{
  return this->_url;
}
int VideoStreamerBase::getBitrate()
{
  return this->_bitrate;
}
bool VideoStreamerBase::isRunning()
{
  return this->_is_running;
}

void VideoStreamerBase::_run()
{
  while (this->_is_running)
  {
    if (isOpenedImpl())
    {
      if (!this->_image_to_stream.empty())
      {
        cv::Mat img = this->_image_to_stream.top();
        writeImpl(img);
    
        while (!this->_image_to_stream.empty())
        {
          this->_image_to_stream.pop();
        }
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(5));
    }
    else
    {
      std::cout << "VideoStreamer.isOpened(): FALSE" << std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      setupImpl();
    }
  }
  std::cout << "streaming == FALSE" << std::endl;
}

void VideoStreamerBase::release()
{
  this->_is_running = false;
  releaseImpl();
}

void VideoStreamerBase::setup(cv::Size size, int port, int bitrate, std::string url)
{
  this->_bitrate = bitrate;
  this->_stream_size = size;

  this->_port = port;
  this->_url = url;

  if (setupImpl())
  {
    // std::cout << "stream ready at rtsp://127.0.0.1:" << this->_port << this->_url << std::endl;

    this->_is_running = true;
    this->_tt = std::thread(&VideoStreamerBase::_run, this);
    this->_tt.detach();
  }
}

void VideoStreamerBase::stream(cv::Mat image)
{
  if (this->_is_running)
  {
    cv::Mat image_stream;
    if (this->_stream_size.height == image.rows && this->_stream_size.width == image.cols)
      image.copyTo(image_stream);
    else
      cv::resize(image, image_stream, this->_stream_size);

    this->_image_to_stream.push(image_stream);
  }
}

bool VideoStreamerBase::setupImpl()
{
  return false;
}
bool VideoStreamerBase::isOpenedImpl()
{
  return false;
}
void VideoStreamerBase::writeImpl(cv::Mat image)
{

}

void VideoStreamerBase::releaseImpl()
{
}

}



